{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1db21ab6",
   "metadata": {},
   "source": [
    "# python之pandas数据处理\n",
    "Pandas 是 Python 生态中用于数据处理和分析的核心库，它提供了高效、灵活的数据结构（如 DataFrame 和 Series）和丰富的函数，能够轻松应对从数据加载、清洗、转换到分析的全流程任务。\n",
    "## 安装\n",
    "```bash\n",
    "pip install pandas\n",
    "```\n",
    "## dataframe对象\n",
    "二维列表，集合各种表格分析功能"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cbe63c75",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>姓名</th>\n",
       "      <th>age</th>\n",
       "      <th>city</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>New York</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>London</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>Paris</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        姓名  age      city\n",
       "0    Alice   25  New York\n",
       "1      Bob   30    London\n",
       "2  Charlie   35     Paris"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 定义一个dataframe对象\n",
    "import pandas as pd\n",
    "data = {\n",
    "    '姓名': ['Alice', 'Bob', 'Charlie'],\n",
    "    'age': [25, 30, 35],\n",
    "    'city': ['New York', 'London', 'Paris']\n",
    "}  \n",
    "df = pd.DataFrame(data)  # 这里使用对象创建，也可以用二维列表创建，但需指定列名columns\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d0c9dd5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 3 entries, 0 to 2\n",
      "Data columns (total 3 columns):\n",
      " #   Column  Non-Null Count  Dtype \n",
      "---  ------  --------------  ----- \n",
      " 0   姓名      3 non-null      object\n",
      " 1   age     3 non-null      int64 \n",
      " 2   city    3 non-null      object\n",
      "dtypes: int64(1), object(2)\n",
      "memory usage: 200.0+ bytes\n"
     ]
    }
   ],
   "source": [
    "# 查看数据概览（数据类型、缺失值等）\n",
    "df.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1eeb6ec9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>age</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>count</th>\n",
       "      <td>3.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>mean</th>\n",
       "      <td>30.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>std</th>\n",
       "      <td>5.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min</th>\n",
       "      <td>25.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>25%</th>\n",
       "      <td>27.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>50%</th>\n",
       "      <td>30.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>75%</th>\n",
       "      <td>32.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max</th>\n",
       "      <td>35.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        age\n",
       "count   3.0\n",
       "mean   30.0\n",
       "std     5.0\n",
       "min    25.0\n",
       "25%    27.5\n",
       "50%    30.0\n",
       "75%    32.5\n",
       "max    35.0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 查看数值型列的统计信息\n",
    "df.describe()\n",
    "# 输出包含：计数、均值、标准差、最小值、分位数、最大值等"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "622b7001",
   "metadata": {},
   "source": [
    "## 数据加载\n",
    "Pandas 支持从多种数据源加载数据，包括 CSV、Excel、SQL 数据库、JSON 等。\n",
    "```python\n",
    "# 从 CSV 文件加载数据\n",
    "df = pd.read_csv('data.csv')\n",
    "\n",
    "# 从 Excel 文件加载数据\n",
    "df = pd.read_excel('data.xlsx')\n",
    "\n",
    "# 从 SQL 数据库加载数据\n",
    "df = pd.read_sql('SELECT * FROM table', connection)\n",
    "\n",
    "# 导出数据\n",
    "df.to_csv('output.csv')\n",
    "df.to_excel('output.xlsx')\n",
    "df.to_json('output.json')\n",
    "```\n",
    "## 数据清洗\n",
    "数据清洗是数据处理的重要步骤，Pandas 提供了丰富的函数来处理缺失值、重复值、异常值等。\n",
    "### 缺失行处理\n",
    "```python\n",
    "# 查看缺失值\n",
    "df.isnull().sum()\n",
    "df[df.isnull().any(axis=1)]\n",
    "# 处理缺失值\n",
    "df.dropna(inplace=True)  # 删除包含缺失值的行\n",
    "# 填充缺失值\n",
    "df.fillna(value=0)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "f571b2bd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.0</td>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3.0</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>NaN</td>\n",
       "      <td>Eve</td>\n",
       "      <td>45</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name  age  score\n",
       "0  1.0    Alice   25   85.5\n",
       "1  2.0      Bob   30    NaN\n",
       "2  3.0     None  NaN   90.0\n",
       "3  3.0  Charlie   35   90.0\n",
       "4  5.0    David   40   88.0\n",
       "5  NaN      Eve   45    NaN\n",
       "6  7.0    Frank   50   95.0\n",
       "7  7.0    Frank   50   95.0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "# 用numpy补充NaN\n",
    "data =  {\n",
    "    'id': [1, 2, 3, 3, 5, np.nan, 7, 7],  # 包含重复值和缺失值\n",
    "    'name': ['Alice', 'Bob', None, 'Charlie', 'David', 'Eve', 'Frank', 'Frank'],  # 包含缺失值和重复值\n",
    "    'age': ['25', 30, np.nan, '35', 40, 45, '50', 50],  # 数值用字符串存储（需转换），包含缺失值\n",
    "    'score': [85.5, np.nan, 90, 90, 88, np.nan, 95, 95]  # 包含缺失值和重复值\n",
    "}\n",
    "df = pd.DataFrame(data)\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "14755880",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "id       0.125\n",
       "name     0.125\n",
       "age      0.125\n",
       "score    0.250\n",
       "dtype: float64"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.isna()  # 返回bool型df\n",
    "df.notna()  # 取反 isna()\n",
    "df.isnull().sum()  # 包含缺失的行统计\n",
    "df.isna().mean()  # 每列缺失值比例\n",
    "# df[df.isnull().any(axis=1)]  # 缺失列统计"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9e45b4dc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name age  score\n",
       "0  1.0    Alice  25   85.5\n",
       "3  3.0  Charlie  35   90.0\n",
       "4  5.0    David  40   88.0\n",
       "6  7.0    Frank  50   95.0\n",
       "7  7.0    Frank  50   95.0"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dropna()  # 包含缺失的行删掉 \n",
    "# df.dropna(axis=1) # 包含缺失的列删掉 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b8a4fddb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.0</td>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name age  score\n",
       "0  1.0    Alice  25   85.5\n",
       "1  2.0      Bob  30    NaN\n",
       "3  3.0  Charlie  35   90.0\n",
       "4  5.0    David  40   88.0\n",
       "6  7.0    Frank  50   95.0\n",
       "7  7.0    Frank  50   95.0"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dropna(how='all')  # 仅当一行中的所有值都为缺失值时才会删除该行\n",
    "df.dropna(thresh=3)  # 保留至少有 3 个非缺失值的行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c48bd0b0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.0</td>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name age  score\n",
       "0  1.0    Alice  25   85.5\n",
       "1  2.0      Bob  30    NaN\n",
       "3  3.0  Charlie  35   90.0\n",
       "4  5.0    David  40   88.0\n",
       "6  7.0    Frank  50   95.0\n",
       "7  7.0    Frank  50   95.0"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dropna(subset=['id', 'name'])  # 删除id、name列中任一列有缺失值的行 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a67c73d8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name age  score\n",
       "0  1.0    Alice  25   85.5\n",
       "3  3.0  Charlie  35   90.0\n",
       "4  5.0    David  40   88.0\n",
       "6  7.0    Frank  50   95.0\n",
       "7  7.0    Frank  50   95.0"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.dropna(how='any', inplace=True)  # inplace 直接修改原 DataFrame，而不是返回新的 DataFrame\n",
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9294bf0a",
   "metadata": {},
   "source": [
    "### 填充缺失值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "874b7ed5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0      Alice\n",
       "1        Bob\n",
       "2    Unknown\n",
       "3    Charlie\n",
       "4      David\n",
       "5        Eve\n",
       "6      Frank\n",
       "7      Frank\n",
       "Name: name, dtype: object"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.fillna(0)  \n",
    "df['name'].fillna('Unknown')  # 指定列填充"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "48b1e052",
   "metadata": {},
   "outputs": [],
   "source": [
    "df.fillna(method='ffill')  # 用前一个非 NaN 值填充\n",
    "df.fillna(method='bfill')  # 用后一个非 NaN 值填充"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71f9cb79",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.0</td>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Unknown</td>\n",
       "      <td>0</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.0</td>\n",
       "      <td>Eve</td>\n",
       "      <td>45</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name age  score\n",
       "0  1.0    Alice  25   85.5\n",
       "1  2.0      Bob  30    0.0\n",
       "2  3.0  Unknown   0   90.0\n",
       "3  3.0  Charlie  35   90.0\n",
       "4  5.0    David  40   88.0\n",
       "5  0.0      Eve  45    0.0\n",
       "6  7.0    Frank  50   95.0\n",
       "7  7.0    Frank  50   95.0"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.fillna({'id': 0, 'name': 'Unknown', 'age': 0, 'score': 0})  # 按列指定填充值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6a0c0234",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0    85.50\n",
       "1    87.75\n",
       "2    90.00\n",
       "3    90.00\n",
       "4    88.00\n",
       "5    91.50\n",
       "6    95.00\n",
       "7    95.00\n",
       "Name: score, dtype: float64"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['score'].interpolate()  # 线性插值\n",
    "# df.interpolate(method='time')  # 时间序列插值"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70f6bd11",
   "metadata": {},
   "source": [
    "### 重复值处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "02b14477",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0    False\n",
       "1    False\n",
       "2    False\n",
       "3    False\n",
       "4    False\n",
       "5    False\n",
       "6    False\n",
       "7    False\n",
       "dtype: bool"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.duplicated()   # 查看重复"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "187aaa56",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1.0</td>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>85.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.0</td>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>3.0</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>NaN</td>\n",
       "      <td>Eve</td>\n",
       "      <td>45</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name  age  score\n",
       "0  1.0    Alice   25   85.5\n",
       "1  2.0      Bob   30    NaN\n",
       "2  3.0     None  NaN   90.0\n",
       "3  3.0  Charlie   35   90.0\n",
       "4  5.0    David   40   88.0\n",
       "5  NaN      Eve   45    NaN\n",
       "7  7.0    Frank   50   95.0"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.drop_duplicates(keep='last', subset=['id', 'name'])  # 处理重复"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b22f5f0a",
   "metadata": {},
   "source": [
    "## 列处理\n",
    "### 字符串处理\n",
    "```python\n",
    "df.columns = ['a', 'b', 'c']  # 等长列表的多行赋值\n",
    "# apply\n",
    "df[A].apply(lambda x: x.str.split('_'))  # 列处理apply\n",
    "# 字符串方法\n",
    "df[B].str.split('_').str[0]  # 字符str处理\n",
    "df.columns = df.columns.str.replace(' ', '_')  # str处理并赋值作用于原df\n",
    "```\n",
    "\n",
    "### 数据类型转换\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "436b318b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0      alice\n",
       "1        bob\n",
       "2        NaN\n",
       "3    charlie\n",
       "4      david\n",
       "5        eve\n",
       "6      frank\n",
       "7      frank\n",
       "Name: name, dtype: object"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以列为单位处理列数据\n",
    "# df['age'] = df['age'] + 1\n",
    "# df['age']\n",
    "df['name'].str.lower()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e2e24e0",
   "metadata": {},
   "source": [
    "## pandas筛选行列数据\n",
    "- 仅筛选行：df[df[A] > 0]\n",
    "- 筛选列：df[['B', 'C']]或者df.loc[:, ['B', 'C']]或者df.iloc[:, [1, 2]]\n",
    "- 筛选行和列：df[df.A > 0][['B', 'C']]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "6b999fdf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>id</th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "      <th>score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2.0</td>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>5.0</td>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "      <td>88.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0.0</td>\n",
       "      <td>Eve</td>\n",
       "      <td>45</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7.0</td>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "      <td>95.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    id     name  age  score\n",
       "1  2.0      Bob   30    0.0\n",
       "3  3.0  Charlie   35   90.0\n",
       "4  5.0    David   40   88.0\n",
       "5  0.0      Eve   45    0.0\n",
       "6  7.0    Frank   50   95.0\n",
       "7  7.0    Frank   50   95.0"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['age'] = df['age'].astype('int')  # 将age列的数据类型改为int\n",
    "df[df['age'] > 28]\n",
    "# df[['name', 'age']]\n",
    "# df[df['age']>18]['name']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e3d141d2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.series.Series'>\n",
      "<class 'pandas.core.frame.DataFrame'>\n"
     ]
    }
   ],
   "source": [
    "# 分清单列和多列的对象类型，不同对象的功能不一样\n",
    "print(type(df['age']))  # 选择单列 Series\n",
    "print(type(df[['age']]))  # 选择多列（列表）DataFrame"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7821a156",
   "metadata": {},
   "source": [
    "### loc和iloc\n",
    "最终效果上与df[df.A > 0][['B', 'C']]一样，但是loc和iloc的效率更高\n",
    "- loc单一操作，无临时对象\n",
    "- loc避免了SettingsWithCopyWarning\n",
    "- 使用loc赋值是明确且安全的，df.loc[条件, [A, B]] = values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d16d498",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>name</th>\n",
       "      <th>age</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>David</td>\n",
       "      <td>40</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Frank</td>\n",
       "      <td>50</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      name  age\n",
       "0    Alice   25\n",
       "2     None  NaN\n",
       "3  Charlie   35\n",
       "4    David   40\n",
       "6    Frank   50\n",
       "7    Frank   50"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 使用 loc (推荐)\n",
    "df.loc[df['score'] > 80, ['name', 'age']]\n",
    "\n",
    "# 链式索引 (不推荐)\n",
    "# df[df['score'] > 80][['name', 'age']]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4c7233aa",
   "metadata": {},
   "source": [
    "### query查询数据\n",
    "\n",
    "query，和df[df[A] > 0]相似，快速的对符合条件的行进行查询筛选\n",
    "- 支持逻辑运算：and, or, not\n",
    "- 支持运算符：> < >= <= == !=\n",
    "- 使用@引用变量\n",
    "```python\n",
    "min_age = 30\n",
    "max_score = 90\n",
    "\n",
    "df.query('age >= @min_age and score <= @max_score')\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "72f23f55",
   "metadata": {},
   "source": [
    "## 数据分组聚合\n",
    "将数据集进行分组，然后对分组进行聚合操作。\n",
    "原df转换为groupby对象，然后对groupby对象进行聚合操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "3e0ec2af",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000017D60EFFE50>"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame({\n",
    "    'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],\n",
    "    'B': ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],\n",
    "    'C': [1, 2, 3, 4, 5, 6, 7, 8],\n",
    "    'D': [10, 20, 30, 40, 50, 60, 70, 80],\n",
    "    'E': pd.to_datetime([\"2025-8-1\", \"2025-8-1\", \"2025-8-1\", \"2025-8-4\", \"2025-8-4\", \"2025-8-8\", \"2025-8-8\", \"2025-8-8\"])\n",
    "})\n",
    "\n",
    "# 按列A分组\n",
    "grouped = df.groupby('A')\n",
    "grouped"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9bcc141f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000017D33BFBE80>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 按列A和列B分组(多列分组)\n",
    "multi_grouped = df.groupby(['A', 'B'])\n",
    "multi_grouped"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "501ad6bf",
   "metadata": {},
   "source": [
    "DataFrameGroupBy 对象有很多新特性：\n",
    "- 聚合函数\n",
    "  - sum()  总和\n",
    "  - mean()  平均值\n",
    "  - median()  中位数\n",
    "  - min()  最小值\n",
    "  - max()  最大值\n",
    "  - std()  标准差\n",
    "  - var()  方差\n",
    "  - size()  样本数\n",
    "  - count()  非 NA 值的数量\n",
    "  - quantile()  分位数\n",
    "- 分组转换函数\n",
    "- 分组过滤函数\n",
    "- 分组统计函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "40f0169b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>bar</th>\n",
       "      <td>12</td>\n",
       "      <td>120</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>foo</th>\n",
       "      <td>24</td>\n",
       "      <td>240</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      C    D\n",
       "A           \n",
       "bar  12  120\n",
       "foo  24  240"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 聚合函数\n",
    "grouped[[\"C\",\"D\",]].sum()   "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ef8a7412",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>C</th>\n",
       "      <th colspan=\"2\" halign=\"left\">D</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>sum</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>bar</th>\n",
       "      <td>12</td>\n",
       "      <td>40.0</td>\n",
       "      <td>20</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>foo</th>\n",
       "      <td>24</td>\n",
       "      <td>48.0</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      C     D    \n",
       "    sum  mean min\n",
       "A                \n",
       "bar  12  40.0  20\n",
       "foo  24  48.0  10"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 对同一列应用多个聚合函数\n",
    "# grouped['C'].agg(['sum', 'mean', 'std'])\n",
    "\n",
    "# 对不同列应用不同聚合函数\n",
    "grouped.agg({'C': 'sum', 'D': ['mean', 'min']})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b8f8595",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0    4.8\n",
       "1    4.0\n",
       "2    4.8\n",
       "3    4.0\n",
       "4    4.8\n",
       "5    4.0\n",
       "6    4.8\n",
       "7    4.8\n",
       "Name: C, dtype: float64"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df['group_mean'] = grouped['C'].transform('mean')  # 计算每组的平均值并广播到原数据形状\n",
    "# grouped['C'].mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b24c8e1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "A     \n",
       "bar  1   -1.000000\n",
       "     3    0.000000\n",
       "     5    1.000000\n",
       "foo  0   -1.327018\n",
       "     2   -0.628587\n",
       "     4    0.069843\n",
       "     6    0.768273\n",
       "     7    1.117488\n",
       "Name: C, dtype: float64"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def normalize(x):\n",
    "    return (x - x.mean()) / x.std()  # 标准化，突出数据的相对差异\n",
    "\n",
    "grouped['C'].apply(normalize)\n",
    "# type(grouped['C'].apply(normalize))  # pandas.core.series.Series"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bd571e8",
   "metadata": {},
   "source": [
    "> 关于series对象apply函数的操作解释\n",
    "\n",
    "上述代码中，apply函数将grouped['C']这一SeriesGroupBy对象传入apply函数，apply函数会返回一个Series对象，该对象包含grouped['C']的每个分组的计算结果。\n",
    "\n",
    "apply(func)在面对Series对象和DataFrame对象时，func都会处理一个Series，df就拆成多个Series对象，然后对每个Series对象进行处理后拼接回df。所以x - x.mean()是对向量进行矩阵处理了。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "9f600b7d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "      <th>E</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>foo</td>\n",
       "      <td>one</td>\n",
       "      <td>1</td>\n",
       "      <td>10</td>\n",
       "      <td>2025-08-01</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>foo</td>\n",
       "      <td>two</td>\n",
       "      <td>3</td>\n",
       "      <td>30</td>\n",
       "      <td>2025-08-03</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>foo</td>\n",
       "      <td>two</td>\n",
       "      <td>5</td>\n",
       "      <td>50</td>\n",
       "      <td>2025-08-05</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>foo</td>\n",
       "      <td>one</td>\n",
       "      <td>7</td>\n",
       "      <td>70</td>\n",
       "      <td>2025-08-07</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>foo</td>\n",
       "      <td>three</td>\n",
       "      <td>8</td>\n",
       "      <td>80</td>\n",
       "      <td>2025-08-08</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     A      B  C   D          E\n",
       "0  foo    one  1  10 2025-08-01\n",
       "2  foo    two  3  30 2025-08-03\n",
       "4  foo    two  5  50 2025-08-05\n",
       "6  foo    one  7  70 2025-08-07\n",
       "7  foo  three  8  80 2025-08-08"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 分组过滤\n",
    "grouped.describe()\n",
    "# grouped.filter(lambda x: len(x) >= 3)  # 筛选出分组中元素个数大于等于3的\n",
    "grouped.filter(lambda x: x['C'].mean() > 4.5)  # 筛选出分组中C列平均值大于4.5的\n",
    "# 会返回符合条件的df中的行（df对象）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7ea51a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "A\n",
       "bar    3\n",
       "foo    5\n",
       "dtype: int64"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "grouped.describe()  # 详细统计\n",
    "grouped.size()  # 统计个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dde9d32c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"8\" halign=\"left\">C</th>\n",
       "      <th colspan=\"5\" halign=\"left\">D</th>\n",
       "      <th colspan=\"8\" halign=\"left\">E</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>...</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>6.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>2.25</td>\n",
       "      <td>4.0</td>\n",
       "      <td>5.75</td>\n",
       "      <td>7.0</td>\n",
       "      <td>2.366432</td>\n",
       "      <td>6.0</td>\n",
       "      <td>40.0</td>\n",
       "      <td>...</td>\n",
       "      <td>70.0</td>\n",
       "      <td>23.664319</td>\n",
       "      <td>6</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-02 06:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-05 18:00:00</td>\n",
       "      <td>2025-08-07 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>2.0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>4.0</td>\n",
       "      <td>5.00</td>\n",
       "      <td>6.0</td>\n",
       "      <td>7.00</td>\n",
       "      <td>8.0</td>\n",
       "      <td>2.828427</td>\n",
       "      <td>2.0</td>\n",
       "      <td>60.0</td>\n",
       "      <td>...</td>\n",
       "      <td>80.0</td>\n",
       "      <td>28.284271</td>\n",
       "      <td>2</td>\n",
       "      <td>2025-08-06 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-05 00:00:00</td>\n",
       "      <td>2025-08-06 00:00:00</td>\n",
       "      <td>2025-08-07 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>2 rows × 24 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      C                                               D        ...        \\\n",
       "  count mean  min   25%  50%   75%  max       std count  mean  ...   max   \n",
       "3   6.0  4.0  1.0  2.25  4.0  5.75  7.0  2.366432   6.0  40.0  ...  70.0   \n",
       "5   2.0  6.0  4.0  5.00  6.0  7.00  8.0  2.828427   2.0  60.0  ...  80.0   \n",
       "\n",
       "                 E                                            \\\n",
       "         std count                 mean                  min   \n",
       "3  23.664319     6  2025-08-04 00:00:00  2025-08-01 00:00:00   \n",
       "5  28.284271     2  2025-08-06 00:00:00  2025-08-04 00:00:00   \n",
       "\n",
       "                                                                  \\\n",
       "                   25%                  50%                  75%   \n",
       "3  2025-08-02 06:00:00  2025-08-04 00:00:00  2025-08-05 18:00:00   \n",
       "5  2025-08-05 00:00:00  2025-08-06 00:00:00  2025-08-07 00:00:00   \n",
       "\n",
       "                             \n",
       "                   max  std  \n",
       "3  2025-08-07 00:00:00  NaN  \n",
       "5  2025-08-08 00:00:00  NaN  \n",
       "\n",
       "[2 rows x 24 columns]"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 传入df，返回一个Series，按这个列的值分组\n",
    "# 按列B的长度分组\n",
    "df.groupby(lambda x: len(df.loc[x, 'B'])).describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "903553b1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"8\" halign=\"left\">C</th>\n",
       "      <th colspan=\"5\" halign=\"left\">D</th>\n",
       "      <th colspan=\"8\" halign=\"left\">E</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>...</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>E</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3.0</td>\n",
       "      <td>2.0</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.50</td>\n",
       "      <td>2.0</td>\n",
       "      <td>2.50</td>\n",
       "      <td>3.0</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>3.0</td>\n",
       "      <td>20.0</td>\n",
       "      <td>...</td>\n",
       "      <td>30.0</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>3</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2.0</td>\n",
       "      <td>4.5</td>\n",
       "      <td>4.0</td>\n",
       "      <td>4.25</td>\n",
       "      <td>4.5</td>\n",
       "      <td>4.75</td>\n",
       "      <td>5.0</td>\n",
       "      <td>0.707107</td>\n",
       "      <td>2.0</td>\n",
       "      <td>45.0</td>\n",
       "      <td>...</td>\n",
       "      <td>50.0</td>\n",
       "      <td>7.071068</td>\n",
       "      <td>2</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>3.0</td>\n",
       "      <td>7.0</td>\n",
       "      <td>6.0</td>\n",
       "      <td>6.50</td>\n",
       "      <td>7.0</td>\n",
       "      <td>7.50</td>\n",
       "      <td>8.0</td>\n",
       "      <td>1.000000</td>\n",
       "      <td>3.0</td>\n",
       "      <td>70.0</td>\n",
       "      <td>...</td>\n",
       "      <td>80.0</td>\n",
       "      <td>10.000000</td>\n",
       "      <td>3</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>3 rows × 24 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "      C                                               D        ...        \\\n",
       "  count mean  min   25%  50%   75%  max       std count  mean  ...   max   \n",
       "E                                                              ...         \n",
       "1   3.0  2.0  1.0  1.50  2.0  2.50  3.0  1.000000   3.0  20.0  ...  30.0   \n",
       "4   2.0  4.5  4.0  4.25  4.5  4.75  5.0  0.707107   2.0  45.0  ...  50.0   \n",
       "8   3.0  7.0  6.0  6.50  7.0  7.50  8.0  1.000000   3.0  70.0  ...  80.0   \n",
       "\n",
       "                 E                                            \\\n",
       "         std count                 mean                  min   \n",
       "E                                                              \n",
       "1  10.000000     3  2025-08-01 00:00:00  2025-08-01 00:00:00   \n",
       "4   7.071068     2  2025-08-04 00:00:00  2025-08-04 00:00:00   \n",
       "8  10.000000     3  2025-08-08 00:00:00  2025-08-08 00:00:00   \n",
       "\n",
       "                                                                  \\\n",
       "                   25%                  50%                  75%   \n",
       "E                                                                  \n",
       "1  2025-08-01 00:00:00  2025-08-01 00:00:00  2025-08-01 00:00:00   \n",
       "4  2025-08-04 00:00:00  2025-08-04 00:00:00  2025-08-04 00:00:00   \n",
       "8  2025-08-08 00:00:00  2025-08-08 00:00:00  2025-08-08 00:00:00   \n",
       "\n",
       "                             \n",
       "                   max  std  \n",
       "E                            \n",
       "1  2025-08-01 00:00:00  NaN  \n",
       "4  2025-08-04 00:00:00  NaN  \n",
       "8  2025-08-08 00:00:00  NaN  \n",
       "\n",
       "[3 rows x 24 columns]"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 按日分组\n",
    "df.groupby(df['E'].dt.day).describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "0424a13a",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\ASUS\\AppData\\Local\\Temp\\ipykernel_15036\\2322586119.py:3: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.\n",
      "  df.groupby(bins).describe()\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"8\" halign=\"left\">C</th>\n",
       "      <th colspan=\"5\" halign=\"left\">D</th>\n",
       "      <th colspan=\"8\" halign=\"left\">E</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>...</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "      <th>min</th>\n",
       "      <th>25%</th>\n",
       "      <th>50%</th>\n",
       "      <th>75%</th>\n",
       "      <th>max</th>\n",
       "      <th>std</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>C</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>(0.999, 2.75]</th>\n",
       "      <td>2.0</td>\n",
       "      <td>1.5</td>\n",
       "      <td>1.0</td>\n",
       "      <td>1.25</td>\n",
       "      <td>1.5</td>\n",
       "      <td>1.75</td>\n",
       "      <td>2.0</td>\n",
       "      <td>0.707107</td>\n",
       "      <td>2.0</td>\n",
       "      <td>15.0</td>\n",
       "      <td>...</td>\n",
       "      <td>20.0</td>\n",
       "      <td>7.071068</td>\n",
       "      <td>2</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(2.75, 4.5]</th>\n",
       "      <td>2.0</td>\n",
       "      <td>3.5</td>\n",
       "      <td>3.0</td>\n",
       "      <td>3.25</td>\n",
       "      <td>3.5</td>\n",
       "      <td>3.75</td>\n",
       "      <td>4.0</td>\n",
       "      <td>0.707107</td>\n",
       "      <td>2.0</td>\n",
       "      <td>35.0</td>\n",
       "      <td>...</td>\n",
       "      <td>40.0</td>\n",
       "      <td>7.071068</td>\n",
       "      <td>2</td>\n",
       "      <td>2025-08-02 12:00:00</td>\n",
       "      <td>2025-08-01 00:00:00</td>\n",
       "      <td>2025-08-01 18:00:00</td>\n",
       "      <td>2025-08-02 12:00:00</td>\n",
       "      <td>2025-08-03 06:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(4.5, 6.25]</th>\n",
       "      <td>2.0</td>\n",
       "      <td>5.5</td>\n",
       "      <td>5.0</td>\n",
       "      <td>5.25</td>\n",
       "      <td>5.5</td>\n",
       "      <td>5.75</td>\n",
       "      <td>6.0</td>\n",
       "      <td>0.707107</td>\n",
       "      <td>2.0</td>\n",
       "      <td>55.0</td>\n",
       "      <td>...</td>\n",
       "      <td>60.0</td>\n",
       "      <td>7.071068</td>\n",
       "      <td>2</td>\n",
       "      <td>2025-08-06 00:00:00</td>\n",
       "      <td>2025-08-04 00:00:00</td>\n",
       "      <td>2025-08-05 00:00:00</td>\n",
       "      <td>2025-08-06 00:00:00</td>\n",
       "      <td>2025-08-07 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>(6.25, 8.0]</th>\n",
       "      <td>2.0</td>\n",
       "      <td>7.5</td>\n",
       "      <td>7.0</td>\n",
       "      <td>7.25</td>\n",
       "      <td>7.5</td>\n",
       "      <td>7.75</td>\n",
       "      <td>8.0</td>\n",
       "      <td>0.707107</td>\n",
       "      <td>2.0</td>\n",
       "      <td>75.0</td>\n",
       "      <td>...</td>\n",
       "      <td>80.0</td>\n",
       "      <td>7.071068</td>\n",
       "      <td>2</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>2025-08-08 00:00:00</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>4 rows × 24 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                  C                                               D        \\\n",
       "              count mean  min   25%  50%   75%  max       std count  mean   \n",
       "C                                                                           \n",
       "(0.999, 2.75]   2.0  1.5  1.0  1.25  1.5  1.75  2.0  0.707107   2.0  15.0   \n",
       "(2.75, 4.5]     2.0  3.5  3.0  3.25  3.5  3.75  4.0  0.707107   2.0  35.0   \n",
       "(4.5, 6.25]     2.0  5.5  5.0  5.25  5.5  5.75  6.0  0.707107   2.0  55.0   \n",
       "(6.25, 8.0]     2.0  7.5  7.0  7.25  7.5  7.75  8.0  0.707107   2.0  75.0   \n",
       "\n",
       "               ...                     E                       \\\n",
       "               ...   max       std count                 mean   \n",
       "C              ...                                              \n",
       "(0.999, 2.75]  ...  20.0  7.071068     2  2025-08-01 00:00:00   \n",
       "(2.75, 4.5]    ...  40.0  7.071068     2  2025-08-02 12:00:00   \n",
       "(4.5, 6.25]    ...  60.0  7.071068     2  2025-08-06 00:00:00   \n",
       "(6.25, 8.0]    ...  80.0  7.071068     2  2025-08-08 00:00:00   \n",
       "\n",
       "                                                                              \\\n",
       "                               min                  25%                  50%   \n",
       "C                                                                              \n",
       "(0.999, 2.75]  2025-08-01 00:00:00  2025-08-01 00:00:00  2025-08-01 00:00:00   \n",
       "(2.75, 4.5]    2025-08-01 00:00:00  2025-08-01 18:00:00  2025-08-02 12:00:00   \n",
       "(4.5, 6.25]    2025-08-04 00:00:00  2025-08-05 00:00:00  2025-08-06 00:00:00   \n",
       "(6.25, 8.0]    2025-08-08 00:00:00  2025-08-08 00:00:00  2025-08-08 00:00:00   \n",
       "\n",
       "                                                              \n",
       "                               75%                  max  std  \n",
       "C                                                             \n",
       "(0.999, 2.75]  2025-08-01 00:00:00  2025-08-01 00:00:00  NaN  \n",
       "(2.75, 4.5]    2025-08-03 06:00:00  2025-08-04 00:00:00  NaN  \n",
       "(4.5, 6.25]    2025-08-07 00:00:00  2025-08-08 00:00:00  NaN  \n",
       "(6.25, 8.0]    2025-08-08 00:00:00  2025-08-08 00:00:00  NaN  \n",
       "\n",
       "[4 rows x 24 columns]"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 按列C的分位数分组\n",
    "bins = pd.qcut(df['C'], q=4)  # 分为4个分位数组\n",
    "df.groupby(bins).describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c887a09a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiYAAAHNCAYAAAAqpbCaAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAK79JREFUeJzt3Ql0FFW+x/F/ICEQIGEJCIGwa9hlVHYVNzYBxVEGR1TccJ6AgDBuqKNxC6Aorow7boAruIKBo4CI0YDCgChLkEVAQwATkkDIUu/877zul53upJu+SX8/5xRNV25X367q7vr1vbeqQhzHcQQAAMACNQJdAQAAABeCCQAAsAbBBAAAWINgAgAArEEwAQAA1iCYAAAAaxBMAACANQgmAADAGgQTAABgDYIJUAWFhITIAw88EOhqVHsrVqww61pvy6PbQsulpaWdtLoB1RXBBChk3rx5ZgdTeGratKmcf/75smTJEqnqNm/ebHaiO3fuDHRVUEm9evUy78+5c+cGuiqATxFMgFI8+OCD8uabb8obb7whd9xxhxw4cEAuvvhi+fTTT6WqB5P4+HiCSRW3bds2SU5OljZt2sjbb78d6OoAPhXq28UB1cPQoUPlrLPOct+/8cYb5ZRTTpEFCxbI8OHDA1q3qiIvL08KCgqkVq1aga5KtfPWW2+ZlrzZs2fLFVdcYYKmhhSgOqDFBPBAgwYNpE6dOhIaWjTLZ2VlybRp0yQ2NlbCw8MlLi5OHn/8cXFdtPvo0aPSsWNHM+n/XQ4dOiTNmzeXfv36SX5+vpl33XXXSb169WTHjh0yePBgqVu3rsTExJjWG08uAv7jjz+aQBUZGWmWc+GFF0pSUlKRbqpRo0aZ/2vXlKur6kTjJ9577z3p3Lmz1K5dW7p27SqLFi0ydS28I9Qdoy5LX/ucOXOkffv2Zn1oC4368ssv5ZxzzjGvSdflpZdeKj///HOR5ym+zOLjNwrT+xMnTjStBbrOtW5nnnmmrFq1qsTj9+7dKzfccIMJllqnLl26yKuvvlqi3G+//SYjR440ddSd/m233SY5OTniDR1j8re//c1sg8aNG8vkyZPl2LFj7r8PGDBATj/99FIfq69Dt7sn5s+fbwKJhuSoqChzH6guaDEBSpGenm52MhoIUlNT5ZlnnpHMzEy5+uqr3WX0b5dccol89dVXpkWlR48e8sUXX8jtt99udoZPPvmkCTOvv/669O/fX+655x554oknzGMnTJhgnkPDQs2aNd3L1JAyZMgQ6dOnj8yaNUuWLl0q999/v2l90IBSlp9++sns+HWHqF1PYWFh8sILL8h5550nK1eulN69e8u5554rkyZNkqefflqmT58unTp1Mo913Zbms88+k9GjR0u3bt0kISFBDh8+bF5rixYtSi3/2muvmR3xzTffbEJAo0aNZPny5SYwtWvXzoQMDWi6PnWd/PDDDxX+pa+v65133jGvSZ/r+eefN+vu+++/NwFK/fHHH2ZduoJMkyZNzFghfQ0ZGRkyZcoUU07rpEFu9+7dZnkaCLUrTwOVNzSU6OvRdaWhUNe1rjPtElTXXHONjBs3TjZt2uSuo9Juma1bt8q99957wuf47rvvZPv27WZda2vUX//6VxPQdJsC1YIDwO21117TpokSU3h4uDNv3rwiZRcvXmz+9vDDDxeZf8UVVzghISHO9u3b3fPuvvtup0aNGs6qVauc9957zzxuzpw5RR43duxYM//WW291zysoKHCGDRvm1KpVyzlw4IB7vpa7//773fdHjhxpyqSkpLjn7du3z6lfv75z7rnnuue5nvurr77yaH1069bNadmypXPkyBH3vBUrVphltG7d2j3v119/NfMiIyOd1NTUIsvo0aOH07RpU+fgwYPueRs2bDDr49prry3y+gsv00VfZ/GvKtd2Wbt2rXverl27nNq1azuXXXaZe96NN97oNG/e3ElLSyvy+CuvvNKJiopysrOzzX3dFrq8d999110mKyvL6dChg0fry1XHSy65pMj88ePHm/n6etWff/5p6njnnXcWKTdp0iSnbt26TmZmpnMiEydOdGJjY817QyUmJprn+PHHH0/4WKAqoCsHKMVzzz0ny5YtM5P252vXx0033SQffvihu8znn39uWjv0F3Zh2rWj+87CR/FoS4F2IYwdO1bGjx9vmvSLP85Ff9m7uH7pHz9+3LQ8lEZbWRITE003hLZKuGhX0VVXXSWrV682rQPe2rdvn2zcuFGuvfZa0zXkonXXFpTSXH755aZVwmX//v2yfv16002jrScu3bt3l4EDB5p1WFF9+/Y13TcurVq1Ml1E2mql60S3wQcffCAjRoww/9cWMNekXSbaYqUtNkrroetLu0dcIiIiTMuPN7QlrLBbb73VvXyl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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 可视化分组\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# 绘制分组箱线图\n",
    "df.boxplot(column='C', by='A')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "616e80ed",
   "metadata": {},
   "source": [
    "## 数据合并和连接\n",
    "merge\\concat\\join\n",
    "1. concat() 沿轴方向拼接两个df pd.concat(objs, axis=0, join='outer', ignore_index=False)\n",
    "2. join() 主要用于基于索引合并df df.join(other, on=None, how='left', lsuffix='', rsuffix='')\n",
    "3. merge()  主要用于基于列合并df pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None)\n",
    "\n",
    "> 对于大型数据集，merge() 通常比 join() 更快\n",
    "\n",
    "> 如果可能，合并前先对连接键排序可以提高性能\n",
    "\n",
    "> 合并后检查结果行数是否符合预期"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "625799bd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>A0</td>\n",
       "      <td>B0</td>\n",
       "      <td>C2</td>\n",
       "      <td>D2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>A1</td>\n",
       "      <td>B1</td>\n",
       "      <td>C3</td>\n",
       "      <td>D3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    A   B   C   D\n",
       "0  A0  B0  C2  D2\n",
       "1  A1  B1  C3  D3"
      ]
     },
     "execution_count": 62,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "简单堆叠数据，不要求列匹配，效率高，但是纵向列拼接数据可能不可靠\n",
    "\"\"\"\n",
    "import pandas as pd\n",
    "\n",
    "df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']})\n",
    "df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']})\n",
    "\n",
    "# # 垂直堆叠（默认axis=0）\n",
    "# result = pd.concat([df1, df2])\n",
    "\n",
    "# # 水平堆叠\n",
    "# result = pd.concat([df1, df2], axis=1)\n",
    "\n",
    "# # 忽略原索引，重新编码索引\n",
    "# result = pd.concat([df1, df2], ignore_index=True)\n",
    "\n",
    "# 不同列名的合并（缺失值用NaN填充）\n",
    "df3 = pd.DataFrame({'C': ['C2', 'C3'], 'D': ['D2', 'D3']})\n",
    "result = pd.concat([df1, df3], axis=1)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51dfd1f0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>key</th>\n",
       "      <th>A</th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>K0</td>\n",
       "      <td>A0</td>\n",
       "      <td>C0</td>\n",
       "      <td>D0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  key   A   C   D\n",
       "0  K0  A0  C0  D0"
      ]
     },
     "execution_count": 70,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "基于索引的联接，语法简洁，但是功能没有merge强大\n",
    "\"\"\"\n",
    "left = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=['K0', 'K1'])\n",
    "right = pd.DataFrame({'C': ['C0', 'C1'], 'D': ['D0', 'D1']}, index=['K0', 'K2'])\n",
    "\n",
    "## 注意观察输出df的索引差异\n",
    "# 基本join（基于索引）\n",
    "result = left.join(right)\n",
    "\n",
    "# 右连接\n",
    "result = left.join(right, how='right')\n",
    "\n",
    "# 外连接\n",
    "result = left.join(right, how='outer')\n",
    "\n",
    "# 内连接\n",
    "result = left.join(right, how='inner')\n",
    "\n",
    "# 指定列作为连接键（不依靠原始片索引）\n",
    "left2 = pd.DataFrame({'key': ['K0', 'K1'], 'A': ['A0', 'A1']})\n",
    "result = left2.join(right, how='inner', on='key')\n",
    "\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "39da065c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "  people key A类门\n",
      "0     P0  K0  A0\n",
      "1     P0  K1  A1\n",
      "2     P1  K0  A2\n",
      "  people key B类门\n",
      "0     P0  K0  B0\n",
      "1     P1  K0  B1\n",
      "2     P1  K0  B2\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>people</th>\n",
       "      <th>key</th>\n",
       "      <th>A类门</th>\n",
       "      <th>B类门</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>P0</td>\n",
       "      <td>K0</td>\n",
       "      <td>A0</td>\n",
       "      <td>B0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>P0</td>\n",
       "      <td>K1</td>\n",
       "      <td>A1</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>P1</td>\n",
       "      <td>K0</td>\n",
       "      <td>A2</td>\n",
       "      <td>B1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>P1</td>\n",
       "      <td>K0</td>\n",
       "      <td>A2</td>\n",
       "      <td>B2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  people key A类门  B类门\n",
       "0     P0  K0  A0   B0\n",
       "1     P0  K1  A1  NaN\n",
       "2     P1  K0  A2   B1\n",
       "3     P1  K0  A2   B2"
      ]
     },
     "execution_count": 79,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\"\n",
    "类似SQL的JOIN操作\n",
    "可以指定一个或多个列作为连接键\n",
    "\"\"\"\n",
    "left = pd.DataFrame({'key': ['K0', 'K1', 'K2'], 'A': ['A0', 'A1', 'A2']})\n",
    "right = pd.DataFrame({'key': ['K0', 'K1', 'K3'], 'B': ['B0', 'B1', 'B3']})\n",
    "\n",
    "# 基本merge（基于共同列'key'）\n",
    "result = pd.merge(left, right, on='key')\n",
    "\n",
    "# 左连接\n",
    "result = pd.merge(left, right, how='left', on='key')\n",
    "\n",
    "# # 右连接\n",
    "# result = pd.merge(left, right, how='right', on='key')\n",
    "\n",
    "# # 外连接\n",
    "# result = pd.merge(left, right, how='outer', on='key')\n",
    "\n",
    "# 多键合并\n",
    "left_multi = pd.DataFrame({'people': ['P0', 'P0', 'P1'],\n",
    "                          'key': ['K0', 'K1', 'K0'],\n",
    "                          'A类门': ['A0', 'A1', 'A2']})\n",
    "right_multi = pd.DataFrame({'people': ['P0', 'P1', 'P1'],\n",
    "                           'key': ['K0', 'K0', 'K0'],\n",
    "                           'B类门': ['B0', 'B1', 'B2']})\n",
    "print(left_multi, right_multi, sep='\\n')\n",
    "result = pd.merge(left_multi, right_multi, how=\"outer\", on=['people', 'key'])\n",
    "\n",
    "# # 不同列名合并\n",
    "# left_diff = pd.DataFrame({'key_left': ['K0', 'K1'], 'A': ['A0', 'A1']})\n",
    "# right_diff = pd.DataFrame({'key_right': ['K0', 'K2'], 'B': ['B0', 'B2']})\n",
    "# result = pd.merge(left_diff, right_diff, left_on='key_left', right_on='key_right', how='outer')\n",
    "\n",
    "result"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d93d1d38",
   "metadata": {},
   "source": [
    "## 数据排序\n",
    "\n",
    "1. 按值排序\n",
    "DataFrame.sort_values(by, axis=0, ascending=True, inplace=False, kind='quicksort', na_position='last')\n",
    "2. 按索引排序\n",
    "DataFrame.sort_index(axis=0, level=None, ascending=True, inplace=False, kind='quicksort', na_position='last', sort_remaining=True)\n",
    "3. 多层索引排序\n",
    "4. 其他排序方法\n",
    "  - 获取排序后第n大/小的值\n",
    "  - 按自定义顺序排序\n",
    "  - 按字符串长度排序\n",
    "> 性能提示：\n",
    "\n",
    "- 大数据集排序时使用 kind='mergesort' 可以获得稳定排序;\n",
    "- 对于非常大的数据集，可以考虑先采样(df.sample(frac=0.1).sort_values(by=['col1', 'col2'], inplace=True, kind='mergesort'))再排序\n",
    "- 内存使用：inplace=True 可以节省内存，但会修改原数据，排序前减少不必要的列可以提升性能\n",
    "- 预先排序索引：如果经常按照索引查询，可以先对索引进行排序，这样查询速度会更快"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c9a706eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1.0</td>\n",
       "      <td>6</td>\n",
       "      <td>b</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2.0</td>\n",
       "      <td>7</td>\n",
       "      <td>c</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2.0</td>\n",
       "      <td>5</td>\n",
       "      <td>a</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3.0</td>\n",
       "      <td>8</td>\n",
       "      <td>d</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4.0</td>\n",
       "      <td>9</td>\n",
       "      <td>e</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>NaN</td>\n",
       "      <td>10</td>\n",
       "      <td>f</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     A   B  C\n",
       "1  1.0   6  b\n",
       "2  2.0   7  c\n",
       "0  2.0   5  a\n",
       "3  3.0   8  d\n",
       "4  4.0   9  e\n",
       "5  NaN  10  f"
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\"\"\" \n",
    "按列排序，数字看大小，字母看ASCII码，默认升序\n",
    "\"\"\"\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "df = pd.DataFrame({\n",
    "    'A': [2, 1, 2, 3, 4, np.nan],\n",
    "    'B': [5, 6, 7, 8, 9, 10],\n",
    "    'C': ['a', 'b', 'c', 'd', 'e', 'f']\n",
    "})\n",
    "\n",
    "# 单列升序排序\n",
    "df.sort_values('A')\n",
    "\n",
    "# 单列降序排序\n",
    "df.sort_values('A', ascending=False)\n",
    "\n",
    "# 多列排序（先按A升序，再按C降序）\n",
    "df.sort_values(['A', 'C'], ascending=[True, False])\n",
    "\n",
    "# # 处理缺失值（将NaN放在前面）\n",
    "# df.sort_values('A', na_position='first')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "905a5336",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 创建乱序索引的DataFrame\n",
    "df = pd.DataFrame({\n",
    "    'A': [1, 2, 3, 4],\n",
    "    'B': [5, 6, 7, 8]\n",
    "}, index=[3, 1, 4, 2])\n",
    "\n",
    "# 按索引升序排序\n",
    "df.sort_index()\n",
    "\n",
    "# 按索引降序排序\n",
    "df.sort_index(ascending=False)\n",
    "\n",
    "# 按列名排序（axis=1）\n",
    "df = pd.DataFrame({\n",
    "    'B': [1, 2, 3],\n",
    "    'A': [4, 5, 6],\n",
    "    'C': [7, 8, 9]\n",
    "})\n",
    "df.sort_index(axis=1)  # 列名按字母顺序排列"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "id": "90762465",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>data</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>letter</th>\n",
       "      <th>number</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">a</th>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">b</th>\n",
       "      <th>2</th>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               data\n",
       "letter number      \n",
       "a      2          1\n",
       "       1          2\n",
       "b      2          3\n",
       "       1          4"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 创建多层索引DataFrame\n",
    "index = pd.MultiIndex.from_tuples([\n",
    "    ('a', 2), ('a', 1), ('b', 2), ('b', 1)\n",
    "], names=['letter', 'number'])\n",
    "df = pd.DataFrame({'data': [1, 2, 3, 4]}, index=index)\n",
    "''' \n",
    "# 先创建一层letter索引的df,再将列number设为第二层索引\n",
    "index = pd.Index(['a', 'a', 'b', 'b'], name='letter')\n",
    "df = pd.DataFrame({'data': [1, 2, 3, 4], \"number\": [2, 1, 2, 1]}, index=index)\n",
    "df = df.set_index('number', append=True)\n",
    "'''\n",
    "df\n",
    "\n",
    "# # 按第一层索引排序\n",
    "# df.sort_index(level='letter')\n",
    "\n",
    "# # 按第二层索引排序\n",
    "# df.sort_index(level='number')\n",
    "\n",
    "# # 多层同时排序\n",
    "# df.sort_index(level=['letter', 'number'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5e240eab",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 获取A列最大的3个值所在行\n",
    "df.nlargest(3, 'A')\n",
    "# 获取B列最小的2个值所在行\n",
    "df.nsmallest(2, 'B')\n",
    "# 定义自定义排序顺序\n",
    "sort_order = {'C': ['b', 'a', 'd', 'c', 'e', 'f']}\n",
    "df['C'] = pd.Categorical(df['C'], categories=sort_order['C'], ordered=True)\n",
    "df.sort_values('C')\n",
    "# 按字符长度排序\n",
    "df = pd.DataFrame({'text': ['aaa', 'bb', 'c', 'dddd']})\n",
    "df.loc[df['text'].str.len().sort_values().index]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "38088cdc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>date</th>\n",
       "      <th>value</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2023-01-01</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>2023-01-02</td>\n",
       "      <td>5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2023-01-03</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2023-01-04</td>\n",
       "      <td>4</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2023-01-05</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2023-01-06</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "        date  value\n",
       "3 2023-01-01      3\n",
       "5 2023-01-02      5\n",
       "0 2023-01-03      0\n",
       "4 2023-01-04      4\n",
       "1 2023-01-05      1\n",
       "2 2023-01-06      2"
      ]
     },
     "execution_count": 91,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''按日期排序'''\n",
    "import numpy as np\n",
    "dates = pd.date_range('20230101', periods=6).to_list()\n",
    "np.random.shuffle(dates)  # 随机打乱，直接作用于原dates列表\n",
    "df = pd.DataFrame({'date': dates, 'value': range(6)})\n",
    "df.sort_values('date')  # 按日期排序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "id": "544385ec",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\ASUS\\AppData\\Local\\Temp\\ipykernel_15036\\637972304.py:7: FutureWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning.\n",
      "  df.groupby('A').apply(lambda x: x.sort_values('B', ascending=False))\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>A</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"3\" valign=\"top\">bar</th>\n",
       "      <th>5</th>\n",
       "      <td>bar</td>\n",
       "      <td>8</td>\n",
       "      <td>1.572240</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>bar</td>\n",
       "      <td>3</td>\n",
       "      <td>-0.845009</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>bar</td>\n",
       "      <td>2</td>\n",
       "      <td>0.831708</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"5\" valign=\"top\">foo</th>\n",
       "      <th>2</th>\n",
       "      <td>foo</td>\n",
       "      <td>7</td>\n",
       "      <td>-0.389240</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>foo</td>\n",
       "      <td>6</td>\n",
       "      <td>0.632457</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>foo</td>\n",
       "      <td>5</td>\n",
       "      <td>-0.052244</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>foo</td>\n",
       "      <td>4</td>\n",
       "      <td>-0.256743</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>foo</td>\n",
       "      <td>1</td>\n",
       "      <td>0.648543</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         A  B         C\n",
       "A                      \n",
       "bar 5  bar  8  1.572240\n",
       "    1  bar  3 -0.845009\n",
       "    3  bar  2  0.831708\n",
       "foo 2  foo  7 -0.389240\n",
       "    4  foo  6  0.632457\n",
       "    7  foo  5 -0.052244\n",
       "    6  foo  4 -0.256743\n",
       "    0  foo  1  0.648543"
      ]
     },
     "execution_count": 92,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''分组后排序'''\n",
    "# 按A列分组，然后在每组内按B列降序排序\n",
    "df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],\n",
    "                   'B': [1, 3, 7, 2, 6, 8, 4, 5],\n",
    "                   'C': np.random.randn(8)\n",
    "})\n",
    "df.groupby('A').apply(lambda x: x.sort_values('B', ascending=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "id": "5186104c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>foo</td>\n",
       "      <td>5</td>\n",
       "      <td>-0.052244</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>foo</td>\n",
       "      <td>4</td>\n",
       "      <td>-0.256743</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>foo</td>\n",
       "      <td>7</td>\n",
       "      <td>-0.389240</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>foo</td>\n",
       "      <td>6</td>\n",
       "      <td>0.632457</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>foo</td>\n",
       "      <td>1</td>\n",
       "      <td>0.648543</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>bar</td>\n",
       "      <td>2</td>\n",
       "      <td>0.831708</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>bar</td>\n",
       "      <td>3</td>\n",
       "      <td>-0.845009</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>bar</td>\n",
       "      <td>8</td>\n",
       "      <td>1.572240</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     A  B         C\n",
       "7  foo  5 -0.052244\n",
       "6  foo  4 -0.256743\n",
       "2  foo  7 -0.389240\n",
       "4  foo  6  0.632457\n",
       "0  foo  1  0.648543\n",
       "3  bar  2  0.831708\n",
       "1  bar  3 -0.845009\n",
       "5  bar  8  1.572240"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''复杂排序条件'''\n",
    "# 按C列绝对值排序\n",
    "# df['C'].abs().argsort()\n",
    "df.iloc[df['C'].abs().argsort()]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "410b907a",
   "metadata": {},
   "source": [
    "## 时间序列处理\n",
    "\n",
    "Pandas 的时间序列功能可以与 NumPy、Matplotlib、Statsmodels 等库无缝集成，适用于金融数据分析、物联网数据处理、日志分析等各种场景。时间序列处理的核心是 DatetimeIndex，合理使用可以极大提升数据处理效率。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "id": "4c20ae08",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "DatetimeIndex(['2023-01-01', '2023-01-02'], dtype='datetime64[ns]', freq=None)"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''创建时间索引'''\n",
    "# 从字符串创建\n",
    "pd.to_datetime(['2023-01-01', '2023-01-02'])\n",
    "\n",
    "# # 生成日期范围\n",
    "# pd.date_range('2023-01-01', periods=5, freq='D')\n",
    "\n",
    "# # 转换时间戳\n",
    "# pd.Timestamp('2023-01-01 12:00:00')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3aa1f5bb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.date(2023, 1, 5)"
      ]
     },
     "execution_count": 108,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''时间属性提取'''\n",
    "dt = pd.Timestamp('2023-01-05 14:30:15')\n",
    "# dt = pd.to_datetime('2023-01-05 14:30:15')\n",
    "dt.date()        # datetime.date(2023, 1, 5)\n",
    "dt.year        # 2023\n",
    "dt.month       # 1\n",
    "dt.day         # 5\n",
    "dt.hour        # 14\n",
    "dt.dayofweek   # 3 (周四)\n",
    "dt.is_leap_year  # 是否闰年"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78ab0548",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>C</th>\n",
       "      <th>D</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2000-01-02</th>\n",
       "      <td>-0.258275</td>\n",
       "      <td>1.382874</td>\n",
       "      <td>0.964531</td>\n",
       "      <td>-0.909731</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-01-09</th>\n",
       "      <td>2.543289</td>\n",
       "      <td>0.925940</td>\n",
       "      <td>-4.115319</td>\n",
       "      <td>2.164299</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-01-16</th>\n",
       "      <td>-1.746683</td>\n",
       "      <td>-1.427951</td>\n",
       "      <td>-1.783156</td>\n",
       "      <td>-1.875469</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-01-23</th>\n",
       "      <td>0.628517</td>\n",
       "      <td>0.422729</td>\n",
       "      <td>-1.630154</td>\n",
       "      <td>-1.059794</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-01-30</th>\n",
       "      <td>2.611142</td>\n",
       "      <td>0.084945</td>\n",
       "      <td>2.366636</td>\n",
       "      <td>1.652238</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-02-06</th>\n",
       "      <td>2.056889</td>\n",
       "      <td>-1.293011</td>\n",
       "      <td>-1.921265</td>\n",
       "      <td>-2.695786</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-02-13</th>\n",
       "      <td>-4.680242</td>\n",
       "      <td>-0.804654</td>\n",
       "      <td>-1.084781</td>\n",
       "      <td>-2.071385</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-02-20</th>\n",
       "      <td>0.250270</td>\n",
       "      <td>3.304601</td>\n",
       "      <td>0.381516</td>\n",
       "      <td>0.188788</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-02-27</th>\n",
       "      <td>-0.435587</td>\n",
       "      <td>-3.656605</td>\n",
       "      <td>0.361140</td>\n",
       "      <td>-0.938367</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2000-03-05</th>\n",
       "      <td>2.243579</td>\n",
       "      <td>-1.323970</td>\n",
       "      <td>1.113116</td>\n",
       "      <td>-1.628457</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                   A         B         C         D\n",
       "2000-01-02 -0.258275  1.382874  0.964531 -0.909731\n",
       "2000-01-09  2.543289  0.925940 -4.115319  2.164299\n",
       "2000-01-16 -1.746683 -1.427951 -1.783156 -1.875469\n",
       "2000-01-23  0.628517  0.422729 -1.630154 -1.059794\n",
       "2000-01-30  2.611142  0.084945  2.366636  1.652238\n",
       "2000-02-06  2.056889 -1.293011 -1.921265 -2.695786\n",
       "2000-02-13 -4.680242 -0.804654 -1.084781 -2.071385\n",
       "2000-02-20  0.250270  3.304601  0.381516  0.188788\n",
       "2000-02-27 -0.435587 -3.656605  0.361140 -0.938367\n",
       "2000-03-05  2.243579 -1.323970  1.113116 -1.628457"
      ]
     },
     "execution_count": 119,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "'''时间维度重采样'''\n",
    "df = pd.DataFrame(np.random.randn(60, 4), index=pd.date_range('1/1/2000', periods=60), columns=['A', 'B', 'C', 'D'])\n",
    "df\n",
    "# # 日数据转为月数据\n",
    "# df.resample('ME').mean()\n",
    "\n",
    "# 日数据降采样为周数据\n",
    "df.resample('W').sum()\n",
    "\n",
    "# # 小时数据升采样为10分钟数据\n",
    "# df.resample('10T').ffill()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "309573a0",
   "metadata": {},
   "source": [
    "## 数据透视表\n",
    "pivot_table 是 pandas 中用于数据透视表分析的强大工具，能对数据进行分组、聚合和重塑，非常适合多维度汇总统计。\n",
    "\n",
    "```python\n",
    "pd.pivot_table(\n",
    "    data,           # 要处理的 DataFrame\n",
    "    values=None,    # 需要聚合的列（可选，默认聚合所有数值列）\n",
    "    index=None,     # 行分组依据\n",
    "    columns=None,   # 列分组依据\n",
    "    aggfunc='mean', # 聚合函数（默认求均值，可传列表指定多个）\n",
    "    fill_value=None, # 用于填充缺失值的值，功能同fillna\n",
    "    margins=False,  # 是否添加汇总行/列（'All'）\n",
    "    margins_name='All' # 汇总行/列的名称\n",
    ")\n",
    "```\n",
    "常见场景：\n",
    "- 按多个维度（如时间、地区、类别）汇总数据。\n",
    "- 快速计算分组后的均值、总和、计数等指标。\n",
    "- 生成可读性强的交叉表（类似 Excel 数据透视表）。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 127,
   "id": "27489e83",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th colspan=\"3\" halign=\"left\">mean</th>\n",
       "      <th colspan=\"3\" halign=\"left\">sum</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>产品</th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>总计</th>\n",
       "      <th>A</th>\n",
       "      <th>B</th>\n",
       "      <th>总计</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>地区</th>\n",
       "      <th>日期</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">华东</th>\n",
       "      <th>2023-01-01</th>\n",
       "      <td>100.0</td>\n",
       "      <td>150.0</td>\n",
       "      <td>125.00</td>\n",
       "      <td>100</td>\n",
       "      <td>150</td>\n",
       "      <td>250</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2023-01-02</th>\n",
       "      <td>110.0</td>\n",
       "      <td>160.0</td>\n",
       "      <td>135.00</td>\n",
       "      <td>110</td>\n",
       "      <td>160</td>\n",
       "      <td>270</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th rowspan=\"2\" valign=\"top\">华北</th>\n",
       "      <th>2023-01-01</th>\n",
       "      <td>80.0</td>\n",
       "      <td>120.0</td>\n",
       "      <td>100.00</td>\n",
       "      <td>80</td>\n",
       "      <td>120</td>\n",
       "      <td>200</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2023-01-02</th>\n",
       "      <td>70.0</td>\n",
       "      <td>100.0</td>\n",
       "      <td>85.00</td>\n",
       "      <td>70</td>\n",
       "      <td>100</td>\n",
       "      <td>170</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>总计</th>\n",
       "      <th></th>\n",
       "      <td>90.0</td>\n",
       "      <td>132.5</td>\n",
       "      <td>111.25</td>\n",
       "      <td>360</td>\n",
       "      <td>530</td>\n",
       "      <td>890</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                mean                 sum          \n",
       "产品                 A      B      总计    A    B   总计\n",
       "地区 日期                                             \n",
       "华东 2023-01-01  100.0  150.0  125.00  100  150  250\n",
       "   2023-01-02  110.0  160.0  135.00  110  160  270\n",
       "华北 2023-01-01   80.0  120.0  100.00   80  120  200\n",
       "   2023-01-02   70.0  100.0   85.00   70  100  170\n",
       "总计              90.0  132.5  111.25  360  530  890"
      ]
     },
     "execution_count": 127,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "\n",
    "# 创建示例数据\n",
    "data = {\n",
    "    '日期': ['2023-01-01', '2023-01-01', '2023-01-01', '2023-01-01', '2023-01-02', '2023-01-02','2023-01-02', '2023-01-02'],\n",
    "    '地区': ['华东', '华北', '华东', '华北', '华东', '华北', '华东', '华北'],\n",
    "    '产品': ['A', 'A', 'B', 'B', 'A', 'A', 'B', 'B'],\n",
    "    '销量': [100, 80, 150, 120, 110, 70, 160, 100],\n",
    "    '销售额': [5000, 4000, 3000, 2400, 5500, 3500, 3250, 2200]\n",
    "}\n",
    "df = pd.DataFrame(data)\n",
    "\n",
    "# 按地区（行）和产品（列）分组，计算平均销量\n",
    "pivot = pd.pivot_table(\n",
    "    data=df,\n",
    "    values='销量',       # 聚合\"销量\"列\n",
    "    index=['地区', '日期'],        # 行索引为\"地区\"\n",
    "    columns='产品',      # 列索引为\"产品\"\n",
    "    aggfunc=['mean', 'sum'],       # 聚合函数：求均值、求和\n",
    "    margins=True,\n",
    "    margins_name='总计'\n",
    ")\n",
    "\n",
    "type(pivot)  # pandas.core.frame.DataFrame  将原df转换为二维分组的聚合表\n",
    "pivot"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f1263f5",
   "metadata": {},
   "source": [
    "## 数据可视化基础\n",
    "pandas 内置了基于 Matplotlib 的可视化功能，无需额外导入复杂绘图库，就能快速对 DataFrame 或 Series 数据进行可视化分析。\n",
    "```python\n",
    "''' \n",
    "参数说明：\n",
    "kind：\n",
    "  - line：折线图\n",
    "  - bar：柱状图\n",
    "  - barh：水平柱状图\n",
    "  - hist：直方图\n",
    "  - scatter：散点图\n",
    "  - box：箱线图\n",
    "  - pie：饼图\n",
    "  - kde：核密度图\n",
    "'''\n",
    "# Series 绘图\n",
    "s.plot(kind=\"图表类型\", ...)\n",
    "\n",
    "# DataFrame 绘图（默认按列绘制多条线/多个系列）\n",
    "df.plot(kind=\"图表类型\", x=\"x轴列名\", y=\"y轴列名\", ...)\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 131,
   "id": "326b6791",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 基础准备\n",
    "# pandas 可视化依赖 Matplotlib，因此需要先确保 Matplotlib 已安装，且在代码中导入matplotlib模块\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt  # 需手动导入，用于调整图表样式\n",
    "\n",
    "# 解决中文显示问题（可选）\n",
    "plt.rcParams[\"font.family\"] = [\"SimHei\"]\n",
    "\n",
    "# 数据准备\n",
    "data = {\n",
    "    \"日期\": pd.date_range(\"2023-01-01\", periods=5),\n",
    "    \"销量\": [120, 150, 130, 180, 160],\n",
    "    \"利润\": [20, 25, 18, 30, 22],\n",
    "    \"产品\": [\"A\", \"A\", \"B\", \"B\", \"A\"]\n",
    "}\n",
    "df = pd.DataFrame(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "20a97c30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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SidPnpT+IMYN0Q8//DCNGDGCDhw4QOvXr6c9e/bczc8OAAAAFsCquBINNlzR4XDCjcjXrl0zOBuLrV69Wi/EGNK3b18JL5MnT6bo6Gjy9/enn376icaMGUMxMTHk5ORE4eHhNHHiRNq/fz8tXLiQVqxYIQGIw9SWLVukyvT1118bfHwOTnzoDsXx+cfFxUlvEQAAAJi+pKQk8vHxobS0NCm2VOvUc555xVPOOeBwALnVOjvLli277eN98cUXMoTFYUfB4SYkJESCDgsKCpJwo9zWq1cvbdXo3nvvpTfffLPcx587dy7Nnj27zPVcDVIeHwAAAExbVlbWXT9GhcJOSkqKhB0eeuLKi7e3d7n3LSgooPHjx9/2MTnolMbVF93rOdjwdHf+/nyb7mKFnO5iY2PLffzp06fTlClTylR2ODChsgMAAGA+lZ0aCTvcLHz69Gk6fPgwvffee/Txxx9L4Hn88cfL3JdXWObqzh2djK1tmQUJed0eTnWlb1OuLw/f19DihnZ2dnIAAACA6auK9+xKraDMQ0dbt26lP/74g8aNG0cRERG0fft2ql27NlUFDw8PmY2lKyMjg+zt7eU2blIufT0AAABAlW8Eys3FR48epVdffbXKgg7jKec800rBjcvcZMxBp/Rt/P15KjwAAABAlYYdDh88ZZxXT3700UcN3ocbh3nqeGV1795demt4NhebM2eOBCvu2+GZW3///bdUlXiYbN68edS/f/9Kfw8AAACwLJUaxmLcB/Pbb7/JTCleTblFixbUpUsXCSW82N+mTZto6dKl0shc6ZOxtaWVK1fKWjq8oCDP/Nq7d6/cxo/9ySef0MCBA6lOnTrk5uamXYMHAAAAoErW2VE0atRIAg/Phrpw4YKsg7Njxw564IEHaN++ffTtt99S79696U7x4oRhYWEyDb30zCke2uJm6W7duknoqSiuGHE1imeUYTYWAACA+czG4oJHjayz88EHH1C9evWkgsMVmFatWsnBKyrzSZw6dUr6aBo3biyVnrvBM70GDRpk8Daemm5o2joAAADAXfXsKKsWt2/fXiovzz77rASd5s2b08aNG+ndd9+VKg+HoVGjRlX0YQEAAABMYxiLG5O5X+fcuXOyL9XVq1fpu+++o+eee056aRRcZurZs6dUgri/xlRgGAsAAMD81OgwFm/wyVs28BAV7y81depU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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制销量和利润的趋势（DataFrame 多列）\n",
    "df.plot(kind=\"line\",  # 绘制折线图\n",
    "        x=\"日期\", y=[\"销量\", \"利润\"],   # 横纵坐标\n",
    "        title=\"销量与利润趋势\",  # 标题\n",
    "        xlabel=\"日期\", ylabel=\"数值\",  # 轴标签\n",
    "        grid=True)  # 显示网格\n",
    "plt.show()  # 显示图表"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 133,
   "id": "ca23a801",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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QNDWF21d0VnbnDoU+HfeeeeZMKLfXYMGDWxfDgCgjjvjJoSkpCRTgKoFq9o68sILL5gi1Ztuukn69OljulYyMzPNa3XUTGJiomnBCIRffvnF/Ek3Q9U535Xz3QEAUKtbRLT75d1335WJEyea2o7WrVvLokWLXHUd8+fPl5SUFJk0aZLpOsnOzpZAo4uh6viuAAC1PohobYa7q666SnJycny+Njk5WXbs2CF5eXmmlkSDC/5HA9ubb74pb7zxhglpOudK48aNTYuR1tr8+OOPZjZZ3d60aVPznkcffdRMCuc9q61j48aNpoXKfT4XAABqqmp51kyrVq1MF061efURqVa3P3laYe6xxx6TW265xXST6KItR/3795f77rvPVbSr0+VrS5OGC+1W0W1adKo1HpU555xzzvADAQBQPWr8Q++C1ZQpU8zIIp0S/7nnnjNzpzz99NPSt29f+f3vf2+6UI4ePWpep4t7bcf1119vntvjy9ChQ/2GFAAAahKCiAX63B19Ls/HH39sRhY5NEDotPhOMa8OddaAcu2113p0g+nr3nvvPZ/HHjNmjDRq1KgaPgUAAGeOIGLBZZddJjNnzpQBAwaYWhCdlO0///mP7NmzR2644QZTS/Ob3/xGRo8eLUVFRSasaNfWM888I5GRkaZupLKiU+220QcTaheOTjIHAEBNRhCxRB8eqPOfPPvss7JkyRITHHTq+wsvvNCjtUOHRWsh8G233WaWVatWyWeffeb32MOGDTPzuwAAUNMRRCxZsWKF6Zr5/vvvZenSpSaUaEvH5s2bpUePHq7XaTi57rrrXOtvvfWWaUEZMmSIWZ8xY4Zcc801ppVFaaHrFVdcQRABariXj71s+xJQjcaEjrF9CTUWQcQS7XLRrhidGVaHN2tXiwYRnR5fh+C6t4i4r+sw37Vr18rWrVvN+hdffCH79++X1atXm/W9e/cy1T0AoNYgiFgyduxYM7nbzp07ZcKECeZhgJ988slJW0S6dOliilVbtmxp1nWOkYsuukguuOACs64TyjF8FwBQWxBELDt48KApLn344YfNM3i8W0Tmzp0rH374oWvo7muvvWaG8jrFqj/88IMJMBpolIaUNWvWeIQZAABqKoKIRfpwwA8++ED++Mc/Su/evU94UrHWguhrnNChw3rfeecd0xqio22cwtSRI0eaMKMOHz58wsy3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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 按产品分组，计算平均销量，用柱状图展示\n",
    "df_grouped = df.groupby(\"产品\")[\"销量\"].mean().reset_index()\n",
    "df_grouped.plot(kind=\"bar\", x=\"产品\", y=\"销量\", \n",
    "                color=[\"#FFA07A\", \"#98FB98\"],  # 自定义颜色\n",
    "                title=\"不同产品平均销量\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d392012d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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97zeMZmaHQAAYE3YyfoILX0YZ0pKSlGcEwAAgP/DjtbjeCrA80MBAACCe+i5Z+DRv2cNQAAAAMW2QFlbcjp06CClS5d2P1r9lltukbCwMK/tvvnmm8I/SwAAgKIOOwsXLizoawAAAAR/2BkyZEjRngkAAECwPC4CAACguCDsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAACsRtgBAABWI+wAAACrEXYAAIDVCDsAAMBqhB0AAGA1wg4AALAaYQcAAFgtIGFn165d0rp1a6lSpYqMGTNGHMfJc/t7771XQkJCsk379+83+1auXNlr+fPPP++39wIAAIKb38NORkaG9OnTR1q2bCkJCQmye/duWbRoUZ77vP7663Ly5En39L//+7/SuHFjiY6Olh9++MGEHc/1GqAAAAACEnbWrVsnp0+flhkzZkjDhg3lxRdflAULFuS5T7ly5UygcU3x8fEyadIkKV26tHz99dfSvn17r/Xh4eF+ez8AACC4+T3sJCUlSbt27UyAUbGxsaZ1x1cabpKTk2XgwIFmfvv27WbSkFOjRg155pln8uwW05al1NRUrwkAANjL72FHw0VMTIx7XmtstIVGu5988dprr8mIESOkVKn/nPr3339vusUSExPlnXfekTlz5si7776b6/5TpkyRyMhI96RdYQAAwF5+DzuhoaHZupkiIiIkPT09331PnDghq1evlqFDh3p1i82cOdMEqG7dusno0aNlxYoVuR5j3LhxphvNNR04cOAS3xEAAAhmof5+wapVq5rRWJ7S0tIkLCws331XrlwpHTt2NKO4cqNdWYcOHcp1vQYtanoAACg5/N6yo0POt27d6p7X+huto9EQlJ/33ntP+vXr554/d+6cNG/e3PzposeuV69eEZw5AAAojvwedjp16mTqdhYuXGjmdTSWdj9p3c6pU6ckMzMzx/000Hz++efSpUsX97KyZctKzZo1ZeTIkWYYu47S0rodrekBAAAISDeW1uzMnz9f4uLizP1wtND4s88+M+u0e0oLja+55pps+/3zn/806xs0aOC1/G9/+5u56WCHDh2kfv36snz5cuncubPf3g8AAAhufg87qm/fvrJv3z7ZsWOHGYYeFRVlluc1ZPymm26Sw4cPZ1t++eWXy8aNG4v0fAEAQPEVkLCjLrvsMunVq1egXh4A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JDMzM9s+/fv3l+XLl8vOnTvlzJkzMmvWLOnevbtZd8cdd8jrr78uhw4dkl9//dWM7HKtAwAA8HvY0RobHUquw8erVasmq1evlpdfftms05odDTRZtWjRQh5++GFp1aqVabXRYDRy5EizTu/Zc9NNN0njxo1NofK1114r/fr1k2Cg3WUTJ07M1m2G7LhWvuNa+Y5r5Tuule+4VsXveoU4vozZKgKHDx+WHTt2mGHoWhzsCx2iri04nTt3zlaX8/XXX8vZs2fNusIuNAYAAMVXwMIOAACAP/AgUAAAYDXCDgAAsBphBwGno/C2bdtm7qINAEBhI+xcgmPHjpkRYPv373cv09FlDRo0MKPOrrnmGvnuu+/c6/RminpfIB11NmbMGJ+e52H79Xr//felfv365llmdevWNfMuJfl65XStPPXo0UMWLVrknv/888/lqquuMiMc9SG7JUlO12r06NFmoIJratSokXsdn6ucP1dPPvmkGd3qiWv132ulP2+enynX5Po55GcwxutzpaOu9a7J+hzMLl26yE8//RTYz5UWKOPiHT161Gnbtq3+CznJyclm2Y8//uhUqVLFeffdd53Dhw87f/rTn5zrr7/erPvtt9+c+vXrO8OHDzfb9ezZ0/nb3/7mlOTrderUKadatWpOUlKSmV+4cKFTr149p6Rfr5yulae3337brNPrpY4cOeJUqlTJmTx5svP999871113nbNx40anJF+r9u3bO2vXrnVOnjxpptTUVLOcz1XOnyv9GaxQoYKzb98+9zKulfe1ysjIcH+edDpw4ID5/aXXhp/Bttm+C6Ojo50dO3Y4P//8s3Pfffc5HTt2DOjnirBTQDfddJPz6quvev0Dr1mzxnnzzTfd2+iHvWzZsubvq1atMkHo7NmzZv7//u//nBtuuMEpydfr3//+t/nizvoLt6Rfr5yulcvx48edmjVrOk2aNHGHnfj4eOfKK690Lly4YOY//PBDZ/DgwU5JvVbnz583XzxpaWnZtudzlf1zlZmZab6sxo8f77U91yrnn0GXF154wXnggQfM3/kZfNXrWr3//vvmP/sumzdvdmrVqhXQzxVhp4B++ukn82dePwxvvPGGExsba/4+adIk55ZbbnGv0x8K/QcvKfK7Xr///rtz7733OnfffbdT0q9XXtdKr9FDDz3kDBkyxB12dNmIESPc26SkpJhfvCX1Wn3zzTcmNDds2NCJiIhwunfvbv53qfhcZf9czZ492ylXrpyzYMECZ/Xq1aYFQ3Gtcv99de7cOadGjRrudfwMOl7X6ttvv3WioqKcxMRE04I/aNAg55577gno54qanQLS/sm8/P777zJ9+nR56KGHzLw+IsNzH+3r1TtBl5Si3LyuV1JSklx22WXy0UcfmUeBlPTrldu12rRpk3z66acydepUr+VZr5U+aC8lJUVKgpyuld58tEmTJrJkyRL517/+ZernHnzwQbOOz5U3ffyO3tlW6wx//vlniY+Plw4dOsi5c+e4Vnl45513pG3btqbeUPEz6K1p06bmUU76RAN90LY+v/KVV14x6wL1uSLsFBH9BVK+fHlTeKv0F27WW2VHRERIenq6lHSxsbHy8ccfm0d+cL1y9ttvv8nw4cPljTfekIoVK3qty3qtSvJ1UoMHD5aEhARp3769+Uzps/M2bNhgfsnyufK2cuVKc+d5DdKTJ0821yktLc0ERa5V7ubMmeP+j6ziZ9Db9u3bZc2aNfLVV1+Z0bZxcXHSs2dPU4gcqM8VYacIbNy4UWbPnm3Sf5kyZcwyfar70aNHvbbTXypZH3tREmmyb9mypSxevNj88tUfDq6Xt+eee86MXujVq1e2dVmvVUm+TjmpUaOGXLhwQX755Rc+V1kcPHjQPLJHRxAp/SLS/3z8+OOPXKtc6LXR6eabb3Yv42fQ27Jly2TgwIGm9SsyMlKef/552bdvn2nFD9TnirBTyJKTk02K1bCjTXku+kWlTXme22VkZJh/+JJKh2rqsEMX/bBr8ClVqhTXKwsNznpbA20S1knn9WG4OmW9VomJieaBuSWVfqb0+rjotdHPlA6D5XPlTW/3oF1WnrQ7Sz8/XKucvffee9K7d2/3f2QVP4Pe9D8XR44c8Qoz2nKTmZkZuM9VkVcFWc6zKCs9Pd1p2rSpqdDXkSCuSQuwdIRI9erV3UPshg0b5vTu3dspyddLi/h01IyOYNORWVrA1qNHD7OO6+V9rXSYq/7dNfXv39+ZNm2aGfapkxbibtiwwRR66zUcNWqUU1Kv1ZIlS5yYmBjnk08+cdavX+9cccUVpoBU8bnyvlbHjh0zP4M6mEI/YzqqRj9L+vPItcq5QFmHUGsxtyd+Bp1so7G06H3GjBnO0qVLna5du5rbiui1CdTnirBTiP/AOtxQ57NOrvU60kE/AFqlrv/YWrFe0mT95fHxxx+bgFixYkXnjjvuMPercCnp1yuvkX6eo7GUflmVKVPGjGrQL3q9z1NJvlZjx451IiMjnapVqzqjR492zpw5417H58r7Wumw4Hbt2pnbZDRo0MD5+9//7l7HtfK+Vvof2rCwMOe7777Lti0/g+K+Vvof/Geffda5/PLLzTW59tprzSjJQH6ueOq5nx0+fFh27Nhh+smjoqICfTpBj+vlO20O3rNnj3Ts2FEqVKgQ6NMJanyufMe18h0/g8H7uSLsAAAAq1GgDAAArEbYAQAAViPsAAAAqxF2AACA1Qg7AADAaoQdAABgNcIOAACwGmEHAABYjbADAADEZv8PEKk2EAXmLbgAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "'''用于展示单组数据的分布特征（频率分布）'''\n",
    "# 绘制销量的分布  \n",
    "df[\"销量\"].plot(kind=\"hist\", bins=5,  # bins：分组数量\n",
    "                color=\"lightblue\", \n",
    "                title=\"销量分布直方图\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 135,
   "id": "9be9097e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAi0AAAHDCAYAAADoTyodAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAM5RJREFUeJzt3Ql8VOW9//EfEPZNlkq0giyClVoELVeURa1SLcsrBqlXtCpyEQEtLbRUqddLpVZwYdFbAgoIaNXrcqUxXhdU1AoVKIggsqghUmQTlC0krJn/6/vkf6YzYZIMCjN5Mp/363Vek7Nk5szJJOeb5/k951QJhUIhAwAAqOCqJnsHAAAA4kFoAQAAXiC0AAAALxBaAACAFwgtAADAC4QWAADgBUILAADwAqEFAAB4gdACAAC8QGgBPPLiiy/ajh07Yq7Lzc21wYMH28GDB0/qPvzud7+z999//zs/z6ZNm+yJJ56w66+/3h555JFj1j/77LN23XXXlfkchw8fdsfkeH300UfWsWNH++qrr+y72Llzpy1YsOCY5XPmzLHt27eX+b0rV660+fPnx1ynn+GyZcts//7932n/gMqG0AJ4YteuXTZw4ED7z//8z/Ayndhefvnl8PpZs2ZZWlqam58+fbqtWbMmvO3ChQutSpUq7mRd2nTuuee6bTZu3BhzHwoKCuyhhx6yvLy8497/jz/+2P7rv/7Lfv7zn1vbtm2tRYsWNnToUFu9erV98sknVlRUFLX95s2bbfHixVHL/vSnP9lvf/vb8LZ6TgWbV155xc3r/SoMrFu3Lmo6dOhQ1PMcOXLEbVe16r/+BFarVs2991jTnXfeGfM9ZWVl2dVXX+0CY2Dfvn3ufWk/y/I///M/UT9LCULKtm3brHPnzrZ+/foynwNINcV/3QBUeA8//LB7VGuKTs6NGze2119/3SZPnuxOzDVr1gyffBU6fvnLX7rg0r59e7e8du3a7iSt4FManXAVLLRtLDqZSp06ddxrlka3NFNQaNWqlTVo0CD8+mpZOO+88+zaa6+1+++/372Ps846K+ZzKHwFASxw8cUXW+/evV1r0+zZs+3888+34cOHu9YfLdd7Xrp0qTsGonCj9/Tpp5+6oBQI1kc+f/Xq1V0I+clPfhL1mgpFWheLwsxf/vIX+4//+A9799133bLnnnvOHecHHnjAylKjRg03Bb755hs79dRTbcmSJda8eXO3rFatWmU+B5BqCC2AB/Qf96RJk9zJ8JJLLnEtBXfffbeNGTPGnbz1H7tO2IG77rrLfvjDH9qgQYOOea6mTZuW+jqlnZwjWz9ELQll0f4VFhbaq6++apdffrlbpnAStJyodUWhpWQoue+++2zq1Km2devWmM972WWXWU5Ojq1YscKFot27d7v3ruOgFpG33347avsvvvjCBacg0D399NOutWjLli1u/plnnnHvWeFHjwoNLVu2jHoOBYeSx0WBTcsUftSioke9ljz22GPWv39/t38bNmywAwcOuOdU0JOg1Sf4foUb/exWrVrljsePfvQj27t3r9smaAlSN5iCYGTIAVIRoQWo4NRloP/2u3Tp4uondHKOpJOkToo6OQZ69eplt956a9S2qpPQSTBosSktbOhEGvlckXQSbtiwoavlOF4KInpu7YPCRtClVa9ePfe6OmErXJTWyqOTvU7aCkGaFBzOOeccF4AUxNT6EoQLPV9kd1Nw8leIUmD55z//GW4VEb1u0PoSS8l1V1xxRTjAxaJuu6eeeio8/49//MN+/OMfu6/VlaWWIbV46eejfWjUqJH7OetnFAQs0fsLjB8/3oVRIJURWoAK7uuvv3b/7asVQif7oBXj+9//vjuZKgx8+eWX4ZOoikBFJ+Y9e/a4k6D+S1fXiv5jj5daJBQSIltDFFrUcvFt9OzZ09WuRFILR+Dmm292dTWRdSaRbrvtNvceZ86c6ephgpO7HhViSj53RkaGTZkyJWqZWlrkhhtucO8lOzvbTjnlFLdsxIgR1rdv35ivrZAS6bPPPnPHJjLMKIToWGn/AgpOOuZlHUPtiwKOutF+/etfuy4ndRWppUwFz2qh0nMo3AGpjtACVHA6QasWJKgNiRx9c8YZZ7iaDp38v/e979k111zj/pNX4HjttdesR48e7kStAlad3NVKUl4Xw9GjR104UjDS6+o5AqoNUVgKWkrKovARuc9qJdJJXpOKedU9pG4evT+9lvZP9SGlUTfMLbfcYh06dLAnn3wyHHgUCFTHoschQ4a4Vhd1uehEH9TglPTee++5RxXjKswFLTQqjr3yyiujtu3Tp88x319aa1CsYxDZciJr1661H/zgB+H5G2+80dXbqEBZXX7p6enhkKP3onkAxQgtgAfq16/vug5++tOfumCiws/g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AMcXWgoKCuzdd9+NuS4UCtn27dutXr16NmDAAEILAABIXmipVq2anX322daxY0dbunSpW/bb3/7WHn30UTt8+LBlZmba2rVrbcSIESd+LwEAQMqLu6ZFrSmye/du27lzp23dutVycnLc41dffWVpacX554477jh5ewsAAFJWXC0thw4dsiNHjoTrVrp16+ZCjAJL165d3df169c/2fsKAABSWFyhpUaNGrZv3z739dGjR23Dhg1WtWpVO+ecc2z9+vUutJx33nkne18BAEAKi6t76G9/+5tdfvnl7mu1sii4FBUV2eDBg92ygwcPumXxys7OttatW7suJdXIqBampKuuusrmzJkT/zsBAACVWpVQUKxSCnULXXjhhXb//ffbli1bXPeQWllKCp5GXUm33nprqc+Xm5trnTt3tunTp9sll1xiv/zlL23z5s22aNGi8DZPP/20/eIXv7DZs2fbwIED43oje/futYYNG9qePXusQYMGcX0PAABIruM5f5fbPaTWkGXLlrmwouHMamGJFVqC4FJeaFGryoQJE+zaa69188OGDbPevXuH13/zzTf2m9/8xo1UAgAAOK6aFgWW119/3Z599lk3rxaXU0891QWaTz/91GrXrm3NmzeP56msT58+UfOqiWnbtm14XoFFw6cLCwvjej4AAJAa4qppWbx4sY0dOzZcv6Lgcd9994W7cs4991y78cYb7YMPPjiuF1erzMSJE91VdOWdd96xt99+2x588MFyv1f7oSalyAkAAKR4aNG1WbKystzXo0aNspo1a9qYMWPc/L333mufffaZK6zt1auXXX/99XG/uIJQ3bp1XUHvgQMH7LbbbrNp06bFNXx6/Pjxrg8smOJt6QEAAJW0ELcktaxcdtlldvrppx+zbseOHbZu3Trr3r17uc+zYMECu/rqq10rTvv27e3uu++2L774wj2/qAD30ksvLbUQVy0tmgJqaVFwoRAXAIAULcSVe+65x6pXrx41AigWFegqiJQnLy/PFfVOnTrVBRZ55plnXOg55ZRTwvc6ev75590tA4JWnkhq7dEEAABSQ1yhRVe+Le8Oz/Lll1/a+++/b2+88Uap26jAVjUxGRkZruA2Pz8/fC2YyGu96L5GXbp0iXvIMwAAqNziCi0zZ84MF87q6rgl6YaJGkmkK+Wq66gs8+fPtzVr1rhpxowZUa0v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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 查看销量与利润的关系\n",
    "df.plot(kind=\"scatter\", x=\"销量\", y=\"利润\", \n",
    "        c=\"red\",  # 点颜色\n",
    "        s=50)  # 点大小\n",
    "plt.title(\"销量与利润相关性\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d7d6ab87",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAG5CAYAAACUU97fAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjUsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvWftoOwAAAAlwSFlzAAAPYQAAD2EBqD+naQAAI8JJREFUeJzt3QuUVeV98OE/MDAj95uKAoYRb8FLiIjS9vOWD41LkIZqE8C09VZrmyjRahpMoqU1kNoEtamXiBRMl5oYa5fp16LGC6bJQi1EiYjYBQUFvCBm5CIwcvvWu1fnLAa5OM5xZl7O86x11nD22WefPYkz/Hj3u/dut2PHjh0BAJCh9q29AwAAH5eQAQCyJWQAgGwJGQAgW0IGAMiWkAEAsiVkAIBsCRkAIFtCBmgxDz30ULzzzju7fW3p0qVx2WWXRX19fYvvF5Cvdq7sC7SEurq6GDhwYFx44YXxwx/+sFg2b968eOONN2LMmDHFn4cPHx5bt26NDh06xF133RWnnXZaDBkypFj3l7/8ZZx66qnxmc98Zo+fkd778ssvx/Lly+NTn/pUi31vQOupasXPBirI9773veJrGnVZtGhR9O7dOx599NG45ZZbYvHixVFdXV28niLmtddeiyuvvLKImYaQOeCAA6J9+/Zx0UUX7fEz1q9fHzfccEOxLlAZHFoCPnGvvvpqTJs2LdIA8Omnnx5Dhw4tRmW+/vWvR8+ePeNb3/pWtGvXrrT+N77xjTj22GPjkksu+dC2+vbtu8dHiiOgshiRAT5R77//fowbNy5GjBgRTz31VKNgSVLQDBo0KDZv3lxadu6558af/umfNlo3zZ1JIzINIzu703BYaudtAfs3IQN8ot59992oqamJm266Kd57770iNjZt2hT9+/cvouPNN9+MlStXxqpVq4r1Z82aVXx9/fXXY+3atcUhpzSS87u/+7uxZcuWj/y5GzdujE6dOkVVlV9zsD8z2Rf4xKW5K927d2+0bMWKFTFgwIDo1q1bnHjiiXHggQc2ipDZs2cXZzLdd9998Z3vfKcImh49ehRxsjfbtm0rginF0uOPP15MGAb2X0IGaBEffPBBnH322XH++efHpZdeWkzITYeO0ryWhx9+OM4444zSuumso9ra2mJUJp3plLzyyivx2GOPfaTPSp/R8D5g/2bMFfjEpUNHaY5Lmrvy29/+tnjesWPHIlbSvJc02TdN1t15RCbZeY7MggULYvLkyTFz5szSsltvvTUOOuigmDBhQvE8HXr64he/GCeddJKQgQohZIBP3De/+c34l3/5lyJkUpB897vfjd/5nd8pJv8mY8eObXR9mLfffjt+/vOfN9pGOqSUDlFde+21jdZLQfTrX/+6eN4wwGxeDFQOP+3AJ+7ee+8tHunw0QUXXBBf/epXG70+bNiwDx1a2lWKoM6dO8cVV1xRWvbAAw9Er1694pxzzimep4nEkyZNKr4ClUHIAC1u3bp1jSb/nnnmmft8Tzpr6e677260LIVN2k6aNLxz3Bx55JFl3mOgrRIyQItKk3bTCMyMGTNKZxQ9/fTTjUZkli1bFocffnij9/3RH/1RccXfnc9aaji09Jvf/Ka0LJ2t9Id/+IfF/Blg/ydkgBaRDvekQPnVr35V3EYgjbA0nC69szRhN10JOEnXmdn5hpNdunSJrl27lpZ9+ctfLi6ml65Rs/P7HVqCyiFkgBaR4iLddqBhrkyDXa/CO2XKlOLspJEjR0a/fv2KC+UdddRRxa0Mdr2H0oYNG4qznn784x83Wp62mS6m99ZbbxXxA+y/XEcGaFPSqdcpena9gB7A7ggZACBb7n4NAGRLyAAA2RIyAEC2hAwAkK02f/r19u3b44033ohu3bo1uoEcALD/SucipfurHXroocVlFrINmRQx7mILAJVpxYoVjW5Dkl3IpJGYhm/EdSUAoHLuyTZw4MBSB2QbMg2Hk1LECBkAqCzt9jGtxGRfACBbQgYAyJaQAQCyJWQAgGwJGQAgW0IGAMiWkAEAsiVkAIBsCRkAoHJCZs2aNVFbWxvLly8vLbvnnnuKywh37tw5zjjjjPif//mf0msLFy6M4cOHR69eveK6664rbgIFANDiIZMiZvTo0Y0iZunSpfE3f/M38cgjj8TixYtj8ODBcdFFFxWv1dfXx3nnnRfDhg2LefPmxaJFi2LWrFll2XEAgCaFzLhx42LChAmNlr3wwgsxYsSIOPHEE+Owww6LSy65JJYsWVK8Nnv27Fi7dm1MmzatCJwpU6bEjBkzyvsdAAAVq0k3jZw+fXpxWGnixImlZUOGDImnnnoqXnzxxeK1O+64I84666zitQULFhSRkw45JSeccEIxKrM3aRQnPXa++yUA+4+NGzcWI/j7snnLtlhZtzEG9OocNR077HXdY445pvR3DZWlSSGTQmVXKWQuuOCC+OxnP1ta57nnnitFyM7vSXew7NChQ9TV1RVzZnZn6tSpMXny5KZ+HwBkIkVMmnJQTvPnzy+ODFB5mhQyu/P888/Hv/3bv8Wzzz5bFPHNN98c5557brG8qqoqqqurG61fU1NT1PieQmbSpElxzTXXlJ6nGEoTiQHYP6S/K1J47MuS1etj4o9fjNvGDY0jDuq2z21SmZodMg888EAxd+aUU04pnt90001x5513FoeVevfuXZy1tLP169dHp06d9ri9FD67xg8A+490COijjJ50WrU2qudsiCHHD43j+vdokX2jAq8js3379li9enWjUEkjLtu2bStOu547d27ptWXLlhXzX1LgAAC0+ojMqaeeGn/yJ39S1PXBBx9cXFOmX79+xcTeNCcmHRqaOXNmXHzxxcVZSyNHjizmyQAAtHrInH/++fHKK6/ErbfeGm+++WYcd9xx8a//+q/RsWPH4vUUNuPHjy8uhte+ffuYM2dOs3caACBpt6MFLrX71ltvFRO70qnYffr0adJ704hOjx49iuvRdO/e/RPbRwDaloWr1sboH/wy/t+V/8ccmQq07iP+/d/sEZmPIh1qGjVqVEt8FABQQdw0EgDIlpABALIlZACAbAkZACBbQgYAyJaQAQCyJWQAgGwJGQAgW0IGAMiWkAEAsiVkAIBsCRkAIFtCBgDIlpABALIlZACAbAkZACBbQgYAyJaQAQCyJWQAgGwJGQAgW0IGAMiWkAEAsiVkAIBsCRkAIFtCBgDIlpABALIlZACAbAkZACBbQgYAyJaQAQCyJWQAgGwJGQAgW0IGAMiWkAEAsiVkAIBsCRkAIFtCBgDIlpABALIlZACAbAkZACBbQgYAyJaQAQCyJWQAgMoJmTVr1kRtbW0sX768eD5r1qxo167dhx5pefLMM8/Epz/96ejbt29Mmzat/N8BAFCx2jc1YkaPHl2KmGTChAlRV1dXeqxYsaKIllNPPTXeeeedGDNmTIwfPz7mzp0b9913Xzz99NOfxPcBAFSgJoXMuHHjinDZWadOnaJnz56lx49+9KMYO3ZsDB48uAiXQw89NL797W/HkUceGTfccEPMmDGj3N8DAFChmhQy06dPj6uuumqPr2/evDluu+22uP7664vnCxYsiDPPPLM41JScfPLJMX/+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TH7+K1ePvYzENDDZFwDIlpABALIlZGjTqqur48Ybbyy+ApXFzz8fRZuf7AsAsCdGZACAbAkZACBbQgYAyJaQoc168skni+sIvf322629K0ALmjVrVnEB1PRIE32HDx8e//Vf/9Xau0UbJWRosx5//PHiyo4///nPW3tXgBZ23HHHRV1dXaxcuTJGjRoVF1xwQWvvEm2UkKHNSgFzxhlnCBmoQB06dIiePXvGgQceGJdffnm8/vrr8c4777T2btEGtflbFFCZ0i+sBQsWxCOPPFL8EgMq109/+tPo379/9O7du7V3hTZIyNAmPfHEE3HUUUfFyJEj4913342XXnopjj/++NbeLaCFpJ/5NCKzZcuW2LZtWzz22GPFKA3syqEl2uz8mBEjRkRNTU189rOfdXgJKszRRx8dL774YjHJ99JLLy0e77//fmvvFm2QkKFNSuHywAMPFP8i+/Wvf12EDVA5OnXqFIMGDYohQ4bEP/7jP8bq1av9g4bdcmiJNmfRokWxatWqePbZZ+Pggw+OX/ziF3HFFVdEfX29e65AhUpnMKZDTLArIzK0OWn05YgjjohTTjml+BfZ2LFji+Pkv/zlL1t714AWkqLlvffeixUrVsT1119f/EMmHW6GXQkZ2pw0fPy5z32u9Lxbt25x8sknO7wEFWThwoXRq1evOPLII4uf/Ycffrg4cwl25e7XAEC2jMgAANkSMgBAtoQMAJAtIQMAZEvIAADZEjJAq98QcNq0aa29G0CmhAzQona9Omu6KegPfvCDfV7F9cADD4zu3bsXt63Y+ZHux3XDDTe0yL4DbY9bFAAt6qyzzornnnsuOnbsWIqW7du3F1HSYPPmzXHllVfG3//935eWpYh58skni6s97+yv//qvi/vyAJVJyAAt6qmnniq+3nnnnXHIIYfEF77whdJrN998cxEs6d5au6qq2vOvq/btDS5DpfLTD7SKdB+dr3zlK7Fp06bSyMwPf/jDeP/993e7/tatW/e4rTSiA1QmIzJAq/ja175W3OH87bffLg4XpZGadEgpxU2S5sh06NCh0YjMSSedtNttXXvttS2230Db4l5LQIsaMmRI/Pd///eHlqdfRenRcJho4MCBsWzZslbYQyAnDi0BLSodBkqTdtOhop0faQQmvdbw/NVXXy3WT3c/TqMxDY927drF66+/HpdffnkxYtOwPP3561//emt/e0ALEzJAi6qrq2t0htKeNJyJlM5uWrhwYSlwPvWpTxUTgqurq+P2228vLf/Od75TnIoNVBYhA7SYNJE3hUxtbe1Hfk8agdlVGn3Z3ZlKzl6CyuOnHmgxjz76aDFHJo2oNCdkPvjgg90uByqPkAFaxJYtW2Ly5MlxySWXNOl9ad7McccdV5oL89prrxVnN6U5NekMp4bl3/zmNz90NWBg/ydkgBbx0EMPFXNZLr300iYH0M5zZI4//vhiRKa+vr7RHJl/+qd/Km5jAFQWp18DLeatt96Kfv36tfZuAPsRIQMAZMuhJQAgW0IGAMiWkAEAsiVkAIBsCRkAIFtCBgDIlpABALIlZACAbAkZACBy9f8BihxEXkEZTJEAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"\"\" \n",
    "箱线图怎么看？\n",
    "- 下须（Lower Whisker）：最小值，通常延伸至数据中不超过「Q1 - 1.5×IQR」的最小值（Q1 为下四分位数，IQR 为四分位距）。\n",
    "- 下四分位数（Q1）：数据中 25% 的数值小于等于此值（第 25 百分位数）。\n",
    "- 中位数（Median, Q2）：数据中间位置的数值（第 50 百分位数），将数据分为上下两半。\n",
    "- 上四分位数（Q3）：数据中 75% 的数值小于等于此值（第 75 百分位数）。\n",
    "- 上须（Upper Whisker）：最大值，通常延伸至数据中不超过「Q3 + 1.5×IQR」的最大值。\n",
    "- 异常值（Outliers）：超出须线范围的点，用散点或圆点表示。\n",
    "其中，四分位距（IQR）= Q3 - Q1，用于衡量数据的离散程度。\n",
    "有什么关键信息需要提取？\n",
    "- 数据集中趋势：中位数（箱内横线）的位置反映数据的中心：中位数偏上，说明数据整体偏左（左偏分布）；偏下则整体偏右（右偏分布）。\n",
    "- 数据离散程度：箱子的高度（IQR）：箱子越矮，数据越集中；越高则离散程度越大。须线长度：须线越长，数据在两端的分布越分散。\n",
    "- 数据对称性\n",
    "- 异常值识别：超出「Q1 - 1.5×IQR」或「Q3 + 1.5×IQR」的点被视为异常值，可能是测量误差、极端值或数据分布特性导致，需进一步分析。\n",
    "\"\"\"\n",
    "# 按产品分组，展示销量的箱线图\n",
    "df.boxplot(column=\"销量\", by=\"产品\",  # by：分组列\n",
    "           grid=False,  # 不显示网格\n",
    "           )\n",
    "plt.suptitle(\"\")  # 去除自动生成的副标题\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "id": "4cfaf723",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 计算各产品销量占比\n",
    "pie_data = df.groupby(\"产品\")[\"销量\"].sum()\n",
    "pie_data.plot(kind=\"pie\", \n",
    "              autopct=\"%1.1f%%\",  # 显示百分比\n",
    "              startangle=90,  # 起始角度\n",
    "              title=\"产品销量占比\")\n",
    "plt.ylabel(\"\")  # 去除y轴标签\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
